package com.qike.duola.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.qike.duola.domain.*;
import com.qike.duola.dto.*;
import com.qike.duola.enums.*;
import com.qike.duola.mapper.*;
import com.qike.duola.service.ApprovalService;
import com.qike.duola.service.DuolaMessageService;
import com.qike.duola.utils.TimeTool;
import com.qike.duola.vo.*;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Eric.zhou
 * @Date: 2020/9/27 11:52
 */
@Service
public class ApprovalServiceImpl implements ApprovalService {


    @Autowired
    private DuolaApprovalTypeMapper approvalTypeMapper;
    @Autowired
    private DuolaApprovalUserMapper approvalUserMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private DuolaApprovalProcessMapper duolaApprovalProcessMapper;
    @Autowired
    private DuolaApprovalSubjectMapper duolaApprovalSubjectMapper;
    @Autowired
    private DuolaApprovalTypeMapper duolaApprovalTypeMapper;
    @Autowired
    private DuolaQuoteMapper duolaQuoteMapper;
    @Autowired
    private DuolaContractMapper duolaContractMapper;
    @Autowired
    private DuolaDeptMapper duolaDeptMapper;
    @Autowired
    private DuolaProjectMapper duolaProjectMapper;
    @Autowired
    private DuolaMessageService duolaMessageService;
    @Value("${duola.Approval}")
    private Boolean approval;

    /**
     * 审批模板列表
     *
     * @return
     */
    @Override
    public ApprovalListVo ApprovalList(ApprovalListDto approvalListDto) {
        ApprovalListVo vo = new ApprovalListVo();
        List<ApprovalList> list = new ArrayList<>();
        DuolaApprovalTypeExample duolaApprovalTypeExample = new DuolaApprovalTypeExample();
        DuolaApprovalTypeExample.Criteria criteria = duolaApprovalTypeExample.createCriteria();
        if (!StringUtils.isEmpty(approvalListDto.getName())) {
            criteria.andTypeNameLike(approvalListDto.getName());
        }
        Page page = PageHelper.startPage(approvalListDto.getStartPage(), approvalListDto.getPageSize());
        List<DuolaApprovalType> duolaApprovalTypes = approvalTypeMapper.selectByExample(duolaApprovalTypeExample);
        for (DuolaApprovalType duolaApprovalType : duolaApprovalTypes) {
            ApprovalList approvalList = new ApprovalList();
            approvalList.setId(duolaApprovalType.getId());
            approvalList.setName(duolaApprovalType.getTypeName());
            approvalList.setType(duolaApprovalType.getApprovalType());
            approvalList.setTime(TimeTool.LocalDateTimeFormat(duolaApprovalType.getAddTime()));
            list.add(approvalList);
        }
        vo.setList(list);
        vo.setTotal(page.getTotal());
        return vo;
    }

    /**
     * 审批模板详情
     *
     * @param id
     * @return
     */
    @Override
//    @Cacheable(value = {"approvalInfo"}, key = "#id")
    public ApprovalInfoVo approvalInfo(Integer id) throws Exception {
        DuolaApprovalType duolaApprovalType = approvalTypeMapper.selectByPrimaryKey(id);
        if (duolaApprovalType == null) {
            throw new Exception(ErrorEnums.ERROR_DATA.getEmsg());
        }
        Map<Long, String> nameMap = new HashMap<>();
        List<SysUser> sysUsers = sysUserMapper.selectByExample(new SysUserExample());
        for (SysUser sysUser : sysUsers) {
            nameMap.put(sysUser.getId(), sysUser.getNickname());
        }
        ApprovalInfoVo vo = new ApprovalInfoVo();
        vo.setName(duolaApprovalType.getTypeName());
        List<ApprovalUserVo> approvalUser = new ArrayList<>();
        List<CopyUserVo> copyUser = new ArrayList<>();
        DuolaApprovalUserExample example = new DuolaApprovalUserExample();
        example.createCriteria().andApprovalTypeIdEqualTo(id).andParentUidEqualTo(0l).andApprovalTypeEqualTo(ApprovalTypeEnums.APPROVAL.getEcode());
        List<DuolaApprovalUser> duolaApprovalUsers = approvalUserMapper.selectByExample(example);
        for (DuolaApprovalUser duolaApprovalUser : duolaApprovalUsers) {
            ApprovalUserVo approvalUserVo = new ApprovalUserVo();
            approvalUserVo.setUid(duolaApprovalUser.getApprovalUid());
            approvalUserVo.setName(nameMap.get(duolaApprovalUser.getApprovalUid()));
            approvalUserVo.setNext(getNext(duolaApprovalUser.getApprovalTypeId(), duolaApprovalUser.getApprovalUid()));
            approvalUser.add(approvalUserVo);
        }
        DuolaApprovalUserExample copy = new DuolaApprovalUserExample();
        copy.createCriteria().andApprovalTypeIdEqualTo(id).andApprovalTypeEqualTo(ApprovalTypeEnums.COPY.getEcode());
        List<DuolaApprovalUser> cpoyUser = approvalUserMapper.selectByExample(copy);
        for (DuolaApprovalUser duolaApprovalUser : cpoyUser) {
            CopyUserVo copyUserVo = new CopyUserVo();
            copyUserVo.setUid(duolaApprovalUser.getApprovalUid());
            copyUserVo.setName(nameMap.get(duolaApprovalUser.getApprovalUid()));
            copyUser.add(copyUserVo);
        }
        vo.setApprovalUser(approvalUser);
        vo.setName(duolaApprovalType.getTypeName());
        vo.setCopyUser(copyUser);
        return vo;
    }

    /**
     * 审批流程人员设置
     *
     * @param approvalProcessSetDto
     */
    @Override
    public void approvalProcessSet(List<ApprovalProcessSetDto> approvalProcessSetDto) throws Exception {
        //判断是否有审批中的如果有就无法设置
        DuolaApprovalSubjectExample subjectExample = new DuolaApprovalSubjectExample();
        subjectExample.createCriteria().andApprovalIdEqualTo(approvalProcessSetDto.get(0).getApprovalTypeId()).andResultEqualTo(ApprovalLResultStatusEnums.ING.getEcode());
        List<DuolaApprovalSubject> duolaApprovalSubjects = duolaApprovalSubjectMapper.selectByExample(subjectExample);
        if (duolaApprovalSubjects.size()>0){
            throw new Exception(ErrorEnums.CANT_EDIT_APPROVAL.getEmsg());
        }
        DuolaApprovalUserExample example = new DuolaApprovalUserExample();
        example.createCriteria().andApprovalTypeIdEqualTo(approvalProcessSetDto.get(0).getApprovalTypeId());
        approvalUserMapper.deleteByExample(example);
        //添加
        for (ApprovalProcessSetDto processSetDto : approvalProcessSetDto) {
            DuolaApprovalUser duolaApprovalUser = new DuolaApprovalUser();
            duolaApprovalUser.setApprovalTypeId(processSetDto.getApprovalTypeId());
            duolaApprovalUser.setApprovalType(processSetDto.getApprovalType());
            duolaApprovalUser.setApprovalUid(processSetDto.getUid());
            if (processSetDto.getApprovalType().equals(ApprovalTypeEnums.APPROVAL.getEcode())) {
                if (processSetDto.getSort() == 0) {
                    duolaApprovalUser.setParentUid(0L);
                } else {
                    duolaApprovalUser.setParentUid(approvalProcessSetDto.get(processSetDto.getSort() - 1).getUid());
                }

            }

            approvalUserMapper.insert(duolaApprovalUser);
        }
    }

    /**
     * 我的审批列表
     *
     * @param waitApprovalListDto
     * @return
     */
    @Override
    public WaitApprovalListVo waitApprovalList(WaitApprovalListDto waitApprovalListDto) {
        List<WaitApprovalList> list = new ArrayList<>();
        WaitApprovalListVo vo = new WaitApprovalListVo();
        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
        DuolaApprovalProcessExample example = new DuolaApprovalProcessExample();
        DuolaApprovalProcessExample.Criteria criteria = example.createCriteria();
        if (waitApprovalListDto.getType() != null) {
            if (waitApprovalListDto.getType().equals(ApprovalLProcessStatusEnums.ING.getEcode())){
                criteria.andStatusEqualTo(waitApprovalListDto.getType());
            }else {
                criteria.andResultEqualTo(waitApprovalListDto.getType());
            }

        }
        //获取所有用户
        Map<Long, String> useMap = new HashMap<>();
        List<SysUser> sysUsers = sysUserMapper.selectByExample(new SysUserExample());
        for (SysUser sysUser : sysUsers) {
            useMap.put(sysUser.getId(), sysUser.getNickname());
        }
        //获取所有审批模板
        Map<Integer, DuolaApprovalType> approvalTypesMap = new HashMap<>();
        List<DuolaApprovalType> duolaApprovalTypes = approvalTypeMapper.selectByExample(new DuolaApprovalTypeExample());
        for (DuolaApprovalType duolaApprovalType : duolaApprovalTypes) {
            approvalTypesMap.put(duolaApprovalType.getId(), duolaApprovalType);
        }
        //获取所有审批主题
        Integer approvalType = waitApprovalListDto.getApprovalType();
        //我发起的
        DuolaApprovalSubjectExample duolaApprovalSubjectExample = new DuolaApprovalSubjectExample();
        if (ApprovalListTypeEnums.my_send.getEcode().equals(approvalType)) {
            DuolaApprovalSubjectExample.Criteria criteria1 = duolaApprovalSubjectExample.createCriteria();
            criteria1.andAddUidEqualTo(userId);
            if (waitApprovalListDto.getType() != null) {
                if (waitApprovalListDto.getType().equals(ApprovalLResultStatusEnums.ING.getEcode())) {
                    criteria1.andResultEqualTo(ApprovalLResultStatusEnums.ING.getEcode());
                } else {
                    criteria1.andResultEqualTo(waitApprovalListDto.getType());
                }
            }
            Page page = PageHelper.startPage(waitApprovalListDto.getStartPage(), waitApprovalListDto.getPageSize());
            List<DuolaApprovalSubject> duolaApprovalSubjects = duolaApprovalSubjectMapper.selectByExample(duolaApprovalSubjectExample);
            for (DuolaApprovalSubject duolaApprovalSubject : duolaApprovalSubjects) {
                WaitApprovalList waitApprovalList = new WaitApprovalList();
                waitApprovalList.setStatus(duolaApprovalSubject.getResult());
                waitApprovalList.setStatusStr(ApprovalLResultStatusEnums.statOf(duolaApprovalSubject.getResult()).getEmsg());
                waitApprovalList.setResult(duolaApprovalSubject.getResult());
                waitApprovalList.setResultStr(ApprovalLResultStatusEnums.statOf(duolaApprovalSubject.getResult()).getEmsg());
                waitApprovalList.setOrderId(duolaApprovalSubject.getOrderId());
                waitApprovalList.setUserName(useMap.get(duolaApprovalSubject.getAddUid()));
                waitApprovalList.setTopic("来自" + useMap.get(duolaApprovalSubject.getAddUid()) + "的" + approvalTypesMap.get(duolaApprovalSubject.getApprovalId()).getTypeName());
                waitApprovalList.setApprovalType(approvalTypesMap.get(duolaApprovalSubject.getApprovalId()).getApprovalType());
                waitApprovalList.setTime((TimeTool.LocalDateTimeFormat(duolaApprovalSubject.getAddTime())));
                list.add(waitApprovalList);
            }
            vo.setTotal(page.getTotal());
            vo.setList(list);
            return vo;
        }
        Map<Integer, DuolaApprovalSubject> subjectMap = new HashMap<>();
        List<Integer> subjectIds = new ArrayList<>();
        List<DuolaApprovalSubject> duolaApprovalSubjects = duolaApprovalSubjectMapper.selectByExample(duolaApprovalSubjectExample);
        for (DuolaApprovalSubject duolaApprovalSubject : duolaApprovalSubjects) {
            subjectMap.put(duolaApprovalSubject.getId(), duolaApprovalSubject);
            subjectIds.add(duolaApprovalSubject.getId());
        }


//        0 待我审批 1我发起的审批,2抄送我的
//        criteria.andApprovalUidEqualTo(userId)

        //待我审批
        if (ApprovalListTypeEnums.wait_my.getEcode().equals(approvalType)) {
            criteria.andApprovalUidEqualTo(userId).andApprovalTypeEqualTo(ApprovalTypeEnums.APPROVAL.getEcode()).andStatusEqualTo(ApprovalLProcessStatusEnums.ING.getEcode());
        }
        //抄送我的
        if (ApprovalListTypeEnums.copy_my.getEcode().equals(approvalType)) {
            criteria.andApprovalUidEqualTo(userId).andApprovalTypeEqualTo(ApprovalTypeEnums.COPY.getEcode());
        }

        //我发起的
        if (ApprovalListTypeEnums.my_send.getEcode().equals(approvalType)) {
            criteria.andApprovalSubjectIdIn(subjectIds);

        }
        Page page = PageHelper.startPage(waitApprovalListDto.getStartPage(), waitApprovalListDto.getPageSize());
        example.setOrderByClause("add_time desc");
        List<DuolaApprovalProcess> duolaApprovalProcesses = duolaApprovalProcessMapper.selectByExample(example);
        for (DuolaApprovalProcess duolaApprovalProcess : duolaApprovalProcesses) {
            WaitApprovalList waitApprovalList = new WaitApprovalList();
            waitApprovalList.setStatus(duolaApprovalProcess.getResult());
            waitApprovalList.setUserName(useMap.get(subjectMap.get(duolaApprovalProcess.getApprovalSubjectId()).getAddUid()));
            waitApprovalList.setStatusStr(ApprovalLResultStatusEnums.statOf(duolaApprovalProcess.getResult()).getEmsg());
            waitApprovalList.setResult(subjectMap.get(duolaApprovalProcess.getApprovalSubjectId()).getResult());
            waitApprovalList.setResultStr(ApprovalLResultStatusEnums.statOf(subjectMap.get(duolaApprovalProcess.getApprovalSubjectId()).getResult()).getEmsg());
            waitApprovalList.setOrderId(subjectMap.get(duolaApprovalProcess.getApprovalSubjectId()).getOrderId());
            waitApprovalList.setTopic("来自" + useMap.get(subjectMap.get(duolaApprovalProcess.getApprovalSubjectId()).getAddUid()) + "的" + approvalTypesMap.get(subjectMap.get(duolaApprovalProcess.getApprovalSubjectId()).getApprovalId()).getTypeName());
            waitApprovalList.setApprovalType(approvalTypesMap.get(subjectMap.get(duolaApprovalProcess.getApprovalSubjectId()).getApprovalId()).getApprovalType());
            waitApprovalList.setTime((TimeTool.LocalDateTimeFormat(subjectMap.get(duolaApprovalProcess.getApprovalSubjectId()).getAddTime())));
            waitApprovalList.setId(duolaApprovalProcess.getId());
            list.add(waitApprovalList);
        }
        vo.setTotal(page.getTotal());
        vo.setList(list);
        return vo;
    }

    /**
     * 审批操作,同意.拒绝
     *
     * @param approvalOperationDto
     */
    @Override
//    public void approvalOperation(Long uid,Integer orderId,Integer type) {
    public void approvalOperation(ApprovalOperationDto approvalOperationDto) {
//        ApprovalOperationDto approvalOperationDto
        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
        DuolaApprovalProcess duolaApprovalProcess = duolaApprovalProcessMapper.selectByPrimaryKey(approvalOperationDto.getId());
        duolaApprovalProcess.setResult(approvalOperationDto.getFlag());
        duolaApprovalProcess.setStatus(ApprovalLProcessStatusEnums.FINISH.getEcode());
        //如果是拒绝 审批单变为拒绝完成 对应单据审批状态变为拒绝状态
        DuolaApprovalSubject duolaApprovalSubject = duolaApprovalSubjectMapper.selectByPrimaryKey(duolaApprovalProcess.getApprovalSubjectId());
        Integer orderId = duolaApprovalSubject.getOrderId();
        SysUserWithBLOBs sysUserWithBLOBs = sysUserMapper.selectByPrimaryKey(duolaApprovalSubject.getAddUid());
        DuolaApprovalType duolaApprovalType = duolaApprovalTypeMapper.selectByPrimaryKey(duolaApprovalSubject.getApprovalId());
        if (approvalOperationDto.getFlag().equals(ApprovalLResultStatusEnums.REFUSE.getEcode())) {
            duolaApprovalSubject.setRefuseReason(approvalOperationDto.getRefuseReason());
            duolaApprovalSubject.setResult(ApprovalLResultStatusEnums.REFUSE.getEcode());
            duolaApprovalSubjectMapper.updateByPrimaryKeySelective(duolaApprovalSubject);
            // todo 单据变为审批失败抄送人员并发送消息给发起人
            //修改原单据
            this.ExaminOrder(orderId, ExamineEnums.EXAMINE_REFUSE.getEcode(), duolaApprovalType.getApprovalType());
            // todo 添加抄送人
            DuolaApprovalUserExample userExample = new DuolaApprovalUserExample();
            userExample.createCriteria().andApprovalTypeIdEqualTo(duolaApprovalSubject.getApprovalId()).andApprovalTypeEqualTo(ApprovalTypeEnums.COPY.getEcode());
            List<DuolaApprovalUser> duolaApprovalUsers = approvalUserMapper.selectByExample(userExample);
            for (DuolaApprovalUser duolaApprovalUser : duolaApprovalUsers) {
                DuolaApprovalProcess approvalProcess = new DuolaApprovalProcess();
                approvalProcess.setApprovalUid(duolaApprovalUser.getApprovalUid());
                approvalProcess.setAddTime(LocalDateTime.now());
                approvalProcess.setApprovalSubjectId(duolaApprovalSubject.getId());
                approvalProcess.setApprovalType(ApprovalTypeEnums.COPY.getEcode());
                approvalProcess.setResult(ApprovalLResultStatusEnums.REFUSE.getEcode());
                approvalProcess.setStatus(ApprovalLProcessStatusEnums.FINISH.getEcode());
                duolaApprovalProcessMapper.insertSelective(approvalProcess);
                //todo 发送消息
                MsgAddDto msgAddDto = new MsgAddDto();
                msgAddDto.setTitle(sysUserWithBLOBs.getNickname() + "提交的审批进度更新了");
                msgAddDto.setMsgType(MessageTypeEnums.system.getEcode());
                msgAddDto.setOriginId(duolaApprovalSubject.getId());
                msgAddDto.setSendUid(approvalProcess.getApprovalUid());
                msgAddDto.setOriginType(duolaApprovalSubject.getApprovalId());
                try {
                    duolaMessageService.msgAdd(msgAddDto);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //todo 发送消息给发起人

            MsgAddDto msgAddDto = new MsgAddDto();
            msgAddDto.setTitle(sysUserWithBLOBs.getNickname() + "提交的审批进度更新了");
            msgAddDto.setMsgType(MessageTypeEnums.system.getEcode());
            msgAddDto.setOriginId(duolaApprovalSubject.getId());
            msgAddDto.setSendUid(duolaApprovalSubject.getAddUid());
            msgAddDto.setOriginType(duolaApprovalSubject.getApprovalId());
            try {
                duolaMessageService.msgAdd(msgAddDto);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            //如果是成功 查找是否有下一级审批 如果有 就继续 没有 对应单据变为审批通过 审批单结束
            DuolaApprovalUserExample userExample = new DuolaApprovalUserExample();
            userExample.createCriteria().andParentUidEqualTo(userId).andApprovalTypeIdEqualTo(duolaApprovalSubject.getApprovalId());
            List<DuolaApprovalUser> duolaApprovalUsers = approvalUserMapper.selectByExample(userExample);
            //如果没有下一级审批
            if (duolaApprovalUsers.size() <= 0) {
                duolaApprovalSubject.setResult(ApprovalLResultStatusEnums.AGREE.getEcode());
                duolaApprovalSubjectMapper.updateByPrimaryKeySelective(duolaApprovalSubject);
                // todo 单据变为审批成功抄送人员并发送消息给发起人
                //添加所有抄送人
                // todo 添加抄送人
                DuolaApprovalUserExample copyUserExample = new DuolaApprovalUserExample();
                copyUserExample.createCriteria().andApprovalTypeIdEqualTo(duolaApprovalSubject.getApprovalId()).andApprovalTypeEqualTo(ApprovalTypeEnums.COPY.getEcode());
                List<DuolaApprovalUser> copyDuolaApprovalUsers = approvalUserMapper.selectByExample(copyUserExample);
                for (DuolaApprovalUser duolaApprovalUser : copyDuolaApprovalUsers) {
                    DuolaApprovalProcess approvalProcess = new DuolaApprovalProcess();
                    approvalProcess.setApprovalUid(duolaApprovalUser.getApprovalUid());
                    approvalProcess.setAddTime(LocalDateTime.now());
                    approvalProcess.setApprovalSubjectId(duolaApprovalSubject.getId());
                    approvalProcess.setApprovalType(ApprovalTypeEnums.COPY.getEcode());
                    approvalProcess.setResult(ApprovalLResultStatusEnums.AGREE.getEcode());
                    approvalProcess.setStatus(ApprovalLProcessStatusEnums.FINISH.getEcode());
                    duolaApprovalProcessMapper.insertSelective(approvalProcess);
                    //todo 发送消息
                    MsgAddDto msgAddDto = new MsgAddDto();
                    msgAddDto.setTitle(sysUserWithBLOBs.getNickname() + "提交的审批进度更新了");
                    msgAddDto.setMsgType(MessageTypeEnums.system.getEcode());
                    msgAddDto.setOriginId(duolaApprovalSubject.getId());
                    msgAddDto.setSendUid(approvalProcess.getApprovalUid());
                    msgAddDto.setOriginType(duolaApprovalSubject.getApprovalId());
                    try {
                        duolaMessageService.msgAdd(msgAddDto);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

//                Integer orderId = duolaApprovalSubject.getOrderId();
                //修改原单据
                this.ExaminOrder(orderId, ExamineEnums.EXAMINE_SUCCESS.getEcode(), duolaApprovalType.getApprovalType());
            } else {
                //todo 发送消息给下一级审批人
                DuolaApprovalUser duolaApprovalUser = duolaApprovalUsers.get(0);
                DuolaApprovalProcess process = new DuolaApprovalProcess();
                process.setAddTime(LocalDateTime.now());
                process.setApprovalUid(duolaApprovalUser.getApprovalUid());
                process.setResult(ApprovalLResultStatusEnums.ING.getEcode());
                process.setApprovalType(ApprovalTypeEnums.APPROVAL.getEcode());
                process.setStatus(ApprovalLProcessStatusEnums.ING.getEcode());
                process.setApprovalSubjectId(duolaApprovalSubject.getId());
                duolaApprovalProcessMapper.insertSelective(process);
                //todo 发送消息
                MsgAddDto msgAddDto = new MsgAddDto();
                msgAddDto.setTitle(sysUserWithBLOBs.getNickname() + "提交了审批");
                msgAddDto.setMsgType(MessageTypeEnums.system.getEcode());
                msgAddDto.setOriginId(duolaApprovalSubject.getId());
                msgAddDto.setSendUid(process.getApprovalUid());
                msgAddDto.setOriginType(duolaApprovalSubject.getApprovalId());
                try {
                    duolaMessageService.msgAdd(msgAddDto);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        duolaApprovalProcessMapper.updateByPrimaryKeySelective(duolaApprovalProcess);
    }

    /**
     * 修改原单据
     *
     * @param orderId
     * @param examine
     * @param approvalType
     */
    @Async
    public void ExaminOrder(Integer orderId, Integer examine, String approvalType) {
        switch (approvalType) {
            //报价单
            case "QUOTE":
                DuolaQuote duolaQuote = duolaQuoteMapper.selectByPrimaryKey(orderId);
                duolaQuote.setExamineStatus(examine);
                duolaQuote.setContractId(null);
                duolaQuoteMapper.updateByPrimaryKeySelective(duolaQuote);
                DuolaContractExample duolaContractExample = new DuolaContractExample();
                duolaContractExample.createCriteria().andQuoteIdEqualTo(orderId).andExamineStatusEqualTo(ExamineEnums.EXAMINE_ING.getEcode()).andParentIdIsNotNull();
                List<DuolaContractWithBLOBs> duolaContracts = duolaContractMapper.selectByExampleWithBLOBs(duolaContractExample);
                if (duolaContracts.size()>0){
                    duolaContracts.get(0).setExamineStatus(examine);
                    duolaContractMapper.updateByPrimaryKeySelective(duolaContracts.get(0));
                }
                break;
            //合同
            case "CONTRACT":
                DuolaContractWithBLOBs duolaContractWithBLOBs = duolaContractMapper.selectByPrimaryKey(orderId);
                duolaContractWithBLOBs.setExamineStatus(examine);
                duolaContractWithBLOBs.setUpdateTime(LocalDateTime.now());
                duolaContractMapper.updateByPrimaryKeySelective(duolaContractWithBLOBs);
                break;
            //工程
            case "PROJECT":
                DuolaProject duolaProject = duolaProjectMapper.selectByPrimaryKey(orderId);
                duolaProject.setUpdateTime(LocalDateTime.now());
                duolaProject.setExamineStatus(examine);
                duolaProjectMapper.updateByPrimaryKeySelective(duolaProject);
                break;
        }
    }

    /**
     * 发起审批
     *
     * @param
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Async
    public void startApproval(Long uid, Integer orderId, Integer type) throws Exception {
        if (approval) {
            Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
            //发起审批
            StartApprovalDto startApprovalDto = new StartApprovalDto();
            startApprovalDto.setAddUid(uid);
            startApprovalDto.setOrderId(orderId);
            startApprovalDto.setApprovalType(type);
            //查询所有需要审批.抄送的人员
            DuolaApprovalUserExample approvalUserExample = new DuolaApprovalUserExample();
            approvalUserExample.createCriteria().andApprovalTypeIdEqualTo(startApprovalDto.getApprovalType()).andParentUidEqualTo(0l);
            List<DuolaApprovalUser> duolaApprovalUsers = approvalUserMapper.selectByExample(approvalUserExample);
            if (duolaApprovalUsers.size() <= 0) {
                throw new Exception(ErrorEnums.NULL_APPROVAL.getEmsg());
            }
            //添加审批主题
            DuolaApprovalSubject duolaApprovalSubject = new DuolaApprovalSubject();
            duolaApprovalSubject.setAddTime(LocalDateTime.now());
            duolaApprovalSubject.setOrderId(startApprovalDto.getOrderId());
            duolaApprovalSubject.setResult(ApprovalLResultStatusEnums.ING.getEcode());
            duolaApprovalSubject.setAddUid(startApprovalDto.getAddUid());
            duolaApprovalSubject.setApprovalId(startApprovalDto.getApprovalType());
            duolaApprovalSubjectMapper.insertSelective(duolaApprovalSubject);
            //一级审批人
            DuolaApprovalProcess process = new DuolaApprovalProcess();
            process.setAddTime(LocalDateTime.now());
            process.setStatus(ApprovalLProcessStatusEnums.ING.getEcode());
            process.setApprovalSubjectId(duolaApprovalSubject.getId());
            process.setApprovalUid(duolaApprovalUsers.get(0).getApprovalUid());
            process.setApprovalType(ApprovalTypeEnums.APPROVAL.getEcode());
            process.setResult(ApprovalLResultStatusEnums.ING.getEcode());
            duolaApprovalProcessMapper.insertSelective(process);
            //todo 发送消息
            SysUserWithBLOBs sysUserWithBLOBs = sysUserMapper.selectByPrimaryKey(userId);
            MsgAddDto msgAddDto = new MsgAddDto();
            msgAddDto.setTitle(sysUserWithBLOBs.getNickname() + "提交了审批");
            msgAddDto.setMsgType(MessageTypeEnums.system.getEcode());
            msgAddDto.setOriginId(duolaApprovalSubject.getId());
            msgAddDto.setSendUid(process.getApprovalUid());
            msgAddDto.setOriginType(type);
            duolaMessageService.msgAdd(msgAddDto);
        }
//    public v


    }

    /**
     * 审批进度查询
     *
     * @param id
     * @param approvalId
     * @return
     */
    @Override
    public List<ApprovalProgressVo> approvalProgress(Integer id, Integer approvalId) {
        List<ApprovalProgressVo> list = new ArrayList<>();
        DuolaApprovalSubjectExample subjectExample = new DuolaApprovalSubjectExample();
        subjectExample.createCriteria().andOrderIdEqualTo(id).andApprovalIdEqualTo(approvalId);
        List<DuolaApprovalSubject> duolaApprovalSubjects = duolaApprovalSubjectMapper.selectByExample(subjectExample);
        if (duolaApprovalSubjects.size() <= 0) {
            return list;
        }

        Map<Long, SysUser> nameMap = new HashMap<>();
        List<SysUser> sysUsers = sysUserMapper.selectByExample(new SysUserExample());
        for (SysUser sysUser : sysUsers) {
            nameMap.put(sysUser.getId(), sysUser);
        }
        Map<Integer, String> deptMap = new HashMap<>();
        List<DuolaDept> duolaDepts = duolaDeptMapper.selectByExample(new DuolaDeptExample());
        for (DuolaDept duolaDept : duolaDepts) {
            deptMap.put(duolaDept.getId(), duolaDept.getDeptName());
        }
        DuolaApprovalSubject duolaApprovalSubject = duolaApprovalSubjects.get(0);
        //添加发起人
        ApprovalProgressVo add = new ApprovalProgressVo();
        add.setName(nameMap.get(duolaApprovalSubject.getAddUid()).getNickname());
        add.setAddTime(TimeTool.LocalDateTimeFormat(duolaApprovalSubject.getAddTime()));
        add.setDeptName(deptMap.get(nameMap.get(duolaApprovalSubject.getAddUid()).getDeptId()));
        add.setStatus(3);
        add.setStatusStr("提交了审批");

        //找出所有已经审批人的流程
        Map<Long, DuolaApprovalProcess> processMap = new HashMap<>();
        DuolaApprovalProcessExample processExample = new DuolaApprovalProcessExample();
        processExample.createCriteria().andApprovalSubjectIdEqualTo(duolaApprovalSubject.getId()).andApprovalTypeEqualTo(ApprovalTypeEnums.APPROVAL.getEcode());
        processExample.setOrderByClause("add_time desc");
        List<DuolaApprovalProcess> duolaApprovalProcesses = duolaApprovalProcessMapper.selectByExample(processExample);
        for (DuolaApprovalProcess duolaApprovalProcess : duolaApprovalProcesses) {
            ApprovalProgressVo vo = new ApprovalProgressVo();
            String s = nameMap.get(duolaApprovalProcess.getApprovalUid()).getNickname();
            vo.setName(s);
            vo.setAddTime(TimeTool.LocalDateTimeFormat(duolaApprovalProcess.getAddTime()));
            vo.setDeptName(deptMap.get(nameMap.get(duolaApprovalProcess.getApprovalUid()).getDeptId()));
            vo.setStatus(duolaApprovalProcess.getResult());
            vo.setStatusStr(ApprovalLResultStatusEnums.statOf(duolaApprovalProcess.getResult()).getEmsg());
            if (duolaApprovalProcess.getResult().equals(ApprovalLResultStatusEnums.REFUSE.getEcode())) {
                vo.setRefuseReason(duolaApprovalSubject.getRefuseReason());
            }
            list.add(vo);
        }
        list.add(add);
//        //找出所有模板人员设置
//        DuolaApprovalUserExample userExample = new DuolaApprovalUserExample();
//        userExample.createCriteria().andApprovalTypeIdEqualTo(duolaApprovalSubject.getApprovalId()).andApprovalTypeEqualTo(ApprovalTypeEnums.APPROVAL.getEcode());
//        List<DuolaApprovalUser> duolaApprovalUsers = approvalUserMapper.selectByExample(userExample);
//        for (DuolaApprovalUser duolaApprovalUser : duolaApprovalUsers) {
//
//        }

        return list;
    }

    /**
     * 查询是否有设置审批流程
     *
     * @param id
     * @return
     */
    @Override
    public void findProcess(Integer id) throws Exception {
        DuolaApprovalUserExample example = new DuolaApprovalUserExample();
        example.createCriteria().andApprovalTypeIdEqualTo(id);
        List<DuolaApprovalUser> duolaApprovalUsers = approvalUserMapper.selectByExample(example);
        if (duolaApprovalUsers.size()<=0){
            throw new Exception(ErrorEnums.NULL_APPROVAL.getEmsg());
        }
    }

    /**
     * 获取子级递归
     *
     * @param approvalTypeId
     * @return
     */
    private ApprovalUserVo getNext(Integer approvalTypeId, Long approvalUid) {
        Map<Long, String> nameMap = new HashMap<>();
        List<SysUser> sysUsers = sysUserMapper.selectByExample(new SysUserExample());
        for (SysUser sysUser : sysUsers) {
            nameMap.put(sysUser.getId(), sysUser.getNickname());
        }
        ApprovalUserVo approvalUserVo = new ApprovalUserVo();
        DuolaApprovalUserExample example = new DuolaApprovalUserExample();
        example.createCriteria().andApprovalTypeIdEqualTo(approvalTypeId).andParentUidEqualTo(approvalUid).andApprovalTypeEqualTo(ApprovalTypeEnums.APPROVAL.getEcode());
        List<DuolaApprovalUser> duolaApprovalUsers = approvalUserMapper.selectByExample(example);
        for (DuolaApprovalUser duolaApprovalUser : duolaApprovalUsers) {
            approvalUserVo.setUid(duolaApprovalUser.getApprovalUid());
            approvalUserVo.setName(nameMap.get(duolaApprovalUser.getApprovalUid()));
            approvalUserVo.setNext(getNext(duolaApprovalUser.getApprovalTypeId(), duolaApprovalUser.getApprovalUid()));
        }
        return approvalUserVo;
    }

}
